package cn.itcast.service.impl;

import cn.itcast.dao.WayBillRepository;
import cn.itcast.domain.delivery.WayBill;
import cn.itcast.index.WayBillIndexRepository;
import cn.itcast.service.WayBillService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class WayBillServiceImpl implements WayBillService {
    @Autowired
    private WayBillRepository wayBillRepository;
    @Autowired
    private WayBillIndexRepository wayBillIndexRepository;

    @Override
    @Transactional//不启用事务对数据的修改操作会默认rollback
    public void save(WayBill wayBill) {
        /*
         根据waybillNum查询该数据是否已经存在
            存在  将weybill数据更新给查询到的对象(id除外)updata
            不存在  save
            生成运单时,应该讲运单状态设一个默认值1
         */
        wayBill.setSignStatus(1);
        WayBill persistWayBill = wayBillRepository.findByWayBillNum(wayBill.getWayBillNum());
        if (persistWayBill == null) {
            //保存订单
            wayBillRepository.save(wayBill);
            //保存索引
            wayBillIndexRepository.save(wayBill);
        } else {
            //手动将waybill数据更新给persistwaybill
            try {
                Integer id = persistWayBill.getId();//保留id
                BeanUtils.copyProperties(persistWayBill, wayBill);//复制属性
                persistWayBill.setId(id);//保留id
                //保存索引
                wayBillIndexRepository.save(persistWayBill);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage());
            }

        }

    }

    @Override
    //从索引库查询数据
    public Page<WayBill> findPageData(WayBill wayBill, Pageable pageable) {
        //对条件进行判断 若是条件都为空 则从数据库查询数据返回
        if (StringUtils.isBlank(wayBill.getWayBillNum()) //运单号
                && StringUtils.isBlank(wayBill.getSendAddress()) //发送地址
                && StringUtils.isBlank(wayBill.getRecAddress())  //接受地址
                && StringUtils.isBlank(wayBill.getSendProNum())  //快递产品类型
                //运单状态为null 或者为默认值0
                && (wayBill.getSignStatus() == null || wayBill.getSignStatus() == 0)) {
            //进行无条件查询
            return wayBillRepository.findAll(pageable);
        } else {
            /*
             从索引库进行查询
             查询条件 各个条件之间的并列关系
              must 必须成立
              must not 必须不成立
              should :条件可以成立 相当于or

              布尔查询 :多条件组合查询 条件对象(查询条件对象)
              searchquery :对索引库进行条件查询时需要传入的对象(包含查询条件对象和查询结果的分页处理)

             */
            BoolQueryBuilder queryBuilder = new BoolQueryBuilder();//创建布尔查询, 多条件组合查询
            //参数处理 构造条件
            if (StringUtils.isNoneBlank(wayBill.getWayBillNum())) {
                //运单号条件
                TermQueryBuilder wayBillNum = new TermQueryBuilder("wayBillNum", wayBill.getWayBillNum());
                //termquery:等值查询 参数1:索引字段 参数2:查询条件
                //where waybillnum = ?;
                queryBuilder.must(wayBillNum);//
            }
            if (StringUtils.isNoneBlank(wayBill.getSendAddress())) {
                //发送地址
                //情况1:单词条模糊搜索
                WildcardQueryBuilder sendAddress1 = new WildcardQueryBuilder("sendAddress", "*" + wayBill.getSendAddress() + "*");
                //wildcardquery 模糊查询  1索引字段 2查询条件
                // where sendAddress like ? ;
                //情况2 多词条组合 进行分词处理 然后进行搜索
                QueryStringQueryBuilder sendAddress2 = new QueryStringQueryBuilder(wayBill.getSendAddress()).field("sendAddress")
                        .defaultOperator(QueryStringQueryBuilder.Operator.AND);
                /*
                  情况2 queryStringquerybuilder 对参数具有分词功能
                   构造传入进行分词的参数(waybill.getsendAddress(),即搜索框用户输入的值)
                   field(索引字段):指定匹配的索引字段
                   defaultoperator(and/or/...):选择各个词条匹配的结果集(交集 或并集...)
                 */
                //构造条件1和条件2的组合条件 满足任意一个条件就可以
                BoolQueryBuilder sendAddress = new BoolQueryBuilder();
                sendAddress.should(sendAddress1);
                sendAddress.should(sendAddress2);
                queryBuilder.must(sendAddress);
            }
            if (StringUtils.isNoneBlank(wayBill.getRecAddress())) {
                //接受地址
                //情况1 单词条查询处理
                WildcardQueryBuilder recAddress1 = new WildcardQueryBuilder("recAddress", "*" + wayBill.getRecAddress() + "*");
                //where recAddress  like ?
                //情况2 组合词条分词处理
                QueryStringQueryBuilder recAddress2 = new QueryStringQueryBuilder(wayBill.getRecAddress()).field("recAddress")
                        .defaultOperator(QueryStringQueryBuilder.Operator.AND);
                BoolQueryBuilder recAddress = new BoolQueryBuilder();
                recAddress.should(recAddress1);
                recAddress.should(recAddress2);
                queryBuilder.must(recAddress);

            }
            if (StringUtils.isNoneBlank(wayBill.getSendProNum())) {
                //速运类型 进行等值查询
                TermQueryBuilder sendProNum = new TermQueryBuilder("sendProNum", wayBill.getSendProNum());
                //where sendProNum =?
                queryBuilder.must(sendProNum);
            }
            if (wayBill.getSignStatus() != null && wayBill.getSignStatus() != 0) {
                //运单状态 等值查询
                TermQueryBuilder signStatus = new TermQueryBuilder("signStatus", wayBill.getSignStatus());
                //where signStatus = ?
                queryBuilder.must(signStatus);
            }
            //构造searchquery 传入封装好的条件对象querybuilder
            SearchQuery searchQuery = new NativeSearchQuery(queryBuilder);//创建searchquery,传入querybuilder
            searchQuery.setPageable(pageable);//设置分页参数
            //对索引库进行条件搜索
            return wayBillIndexRepository.search(searchQuery);
        }
    }

    @Override
    public WayBill findByWayBillNum(String wayBillNum) {
        return wayBillRepository.findByWayBillNum(wayBillNum);
    }

    @Override
    public List<WayBill> findAll() {
        return  wayBillRepository.findAll();
    }
}
